<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Tree_model extends CI_Model{
    
    private $u_menu;
    
    public function __construct() {
        parent::__construct();
        //$this->load->helper('directory');
        $this->load->model('role_model');
        $this->load->model('node_model');
        $this->load->model('setting_model');
        $this->load->model('user_profiles');
        $this->u_menu = $this->user_profiles->get_u_menu();
    }

    //$this->firephp->log("-" . $node->get_path());
    
    /**!!!
     * Основная функция для рисования дерева (точка входа)
     * Return all tree
     * @return string Tree
     */
    public function get_tree_directory(){
        $perms = $this->role_model->get_permissions($this->session->userdata('role'));
        $root_node = $this->node_model->get_root();
        if(array_key_exists($root_node->get_hash(), $perms)){
            return $this->make_tree_directory($root_node);
        }else{
            return $this->make_tree_directory_with_permissions($perms);
        }
    }

    /**!!!
     * 
     * @param BynaryNode $node_obj
     * @return string
     * 
     */
    private function make_tree_directory($node_obj,$with_chech=false){
        $childs = $this->node_model->get_children($node_obj->get_id());

        $tree = sprintf("<ul style='display:%s' class=\"ul_item\">\n",$this->user_profiles->get_ul_style_display($node_obj));
        foreach($childs as $node){
            if($node->get_is_folder() == 1){
                $fstatus = $this->folder_status($node->get_hash());
                
                $rel = $this->node_model->is_embed_elements($node->get_hash());

                $check_str = $with_chech?'<input type="checkbox" class="checknode">':'';
//                $tree .= sprintf('<li class="dir%3$s">'.$check_str.'<img src="%4$s" align="bottom" id="img%1$s" class="folder hand" alt="Развернуть/Свернуть" title="Развернуть/Свернуть"><a href="/chart/node/%1$s" class="dirhref" rel="%5$d" title="%2$s">%2$s</a> '."\n",$node->get_hash(),$node->get_title_short(),$fstatus['folder_status'],$fstatus['folder_image'],$rel);
                $data_titlefull = ($with_chech)?' data-titlefull="'.$node->get_title_full().'"':""; 
                $tree .= sprintf('<li class="dir%3$s" id="%1$s"%6$s>'.$check_str.'<img src="%4$s" align="bottom" class="folder hand" alt="Развернуть/Свернуть" title="Развернуть/Свернуть"><a href="/chart/node/%1$s" class="dirhref" rel="%5$d" title="%2$s">%2$s</a> '."\n",$node->get_hash(),$node->get_title_short(),$fstatus['folder_status'],$fstatus['folder_image'],$rel,$data_titlefull);
                if($fstatus['is_open']){
                    $tree .= $this->make_tree_directory($node,$with_chech);
                }
                $tree .= '</li>';
            }else{
                if($with_chech)
                    $tree .= sprintf('<li class="file" id="%1$s" data-titlefull="%3$s"><nobr><input type="checkbox" class="checknode">&nbsp;<a href="/chart/node/%1$s" title="%2$s" target="_blank">%2$s</a></nobr></li>'."\n",$node->get_hash(),$node->get_title_short(),$node->get_title_full());
                else
                    $tree .= sprintf('<li class="file" id="%1$s"><img src="/images/star-small.gif" align="bottom" alt="Добавить в закладки" title="Добавить в закладки" class="fav hand">&nbsp;<a href="/chart/node/%1$s" title="%2$s">%2$s</a></li>'."\n",$node->get_hash(),$node->get_title_short());
//                    $tree .= sprintf('<li class="file"><img src="/images/star-small.gif" align="bottom" alt="Добавить в закладки" title="Добавить в закладки" class="fav hand" id="bkm%1$s">&nbsp;<a href="/chart/node/%1$s" title="%2$s">%2$s</a></li>'."\n",$node->get_hash(),$node->get_title_short());
            }
        }
        $tree .= '</ul>';
        return $tree;
    }
    
    /**!!!
     * 
     * 
     */
    private function make_tree_directory_with_permissions($permissions){
        $first_nodes_ary = $this->get_all_first_nodes($permissions);
        
        $tree = "<ul id='ul0' style='display:block' class=\"ul_item\">\n";
        foreach ($first_nodes_ary as $node_obj) {
            $fstatus = $this->folder_status($node_obj->get_hash());

            $tree .= sprintf('<li class="dir%3$s" id="%1$s"><img src="%4$s" align="bottom" class="folder hand" alt="Развернуть/Свернуть" title="Развернуть/Свернуть">'.
                     '<a href="/chart/node/%1$s" class="dirhref" rel="0">%2$s</a> '."\n",$node_obj->get_hash(),$node_obj->get_title_short(),$fstatus['folder_status'],$fstatus['folder_image']);
            if($fstatus['is_open']){
//                $st_tree = sprintf('<ul id="ul%s" style="display:%s" class="ul_item">'."\n",$node_obj->get_hash(),'block');
                $st_tree = '<ul style="display:block" class="ul_item">'."\n";
                
                foreach ($permissions as $perm_node) {
                    if($node_obj->get_hash() === $perm_node->get_hash() ){
                        $tree .= $this->make_tree_directory($perm_node);
                        $st_tree = "";
                        break;
                    }else{
                        if($this->role_model->is_allow_node($node_obj, $perm_node)){
                            $st_tree .= $this->make_tree_sub_directory($perm_node);
                        }
                    }
                }
                $tree .= empty($st_tree)?"":$st_tree."</ul>\n";
            }
            $tree .= "</li>\n";
        }
        $tree .= '</ul>';
        return $tree;
    }
    
    /**
     * Alias fffff
     * @param BynaryNode $node_obj
     * @return string
     */
    private function make_tree_sub_directory($node_obj){
        $tree = '';
        if($node_obj->is_folder()){
            $fstatus = $this->folder_status($node_obj->get_hash());
            
            $rel = $this->node_model->is_embed_elements($node_obj->get_hash());

//            $tree .= sprintf('<li class="dir%3$s"><img src="%4$s" align="bottom" id="img%1$s" class="folder hand" alt="Развернуть/Свернуть" title="Развернуть/Свернуть"><a href="/chart/node/%1$s" class="dirhref" rel="%5$d">%2$s</a> '."\n",$node_obj->get_hash(),$node_obj->get_title_cutter(1),$fstatus['folder_status'],$fstatus['folder_image'],$rel);
            $tree .= sprintf('<li class="dir%3$s" id="%1$s"><img src="%4$s" align="bottom" class="folder hand" alt="Развернуть/Свернуть" title="Развернуть/Свернуть"><a href="/chart/node/%1$s" class="dirhref" rel="%5$d">%2$s</a> '."\n",$node_obj->get_hash(),$node_obj->get_title_cutter(1),$fstatus['folder_status'],$fstatus['folder_image'],$rel);
            if($fstatus['is_open']){
                $tree .= $this->make_tree_directory($node_obj);
            }
        }else{
//            $tree .= sprintf('<li class="file"><img src="/images/star-small.gif" align="bottom" alt="Добавить в закладки" title="Добавить в закладки" class="fav hand" id="bkm%1$s">&nbsp;<a href="/chart/node/%1$s" title="%2$s">%2$s</a></li>'."\n",$node_obj->get_hash(),$node_obj->get_title_cutter(1));
            $tree .= sprintf('<li class="file" id="%1$s"><img src="/images/star-small.gif" align="bottom" alt="Добавить в закладки" title="Добавить в закладки" class="fav hand">&nbsp;<a href="/chart/node/%1$s" title="%2$s">%2$s</a></li>'."\n",$node_obj->get_hash(),$node_obj->get_title_cutter(1));
        }
        return $tree;
    }
    
    /**!!!
     * 
     * For ajax requests, return part tree
     * @param string $node_hash
     * @return string 
     */
    public function get_tree_node($node_hash){
        
        $node_obj = $this->node_model->get_node($node_hash);
        $permissions = $this->role_model->get_permissions($this->session->userdata['role']);
        
//        $tree = "<ul id='ul". $node_obj->get_hash() . "' style='display:none' class=\"ul_item\">\n";
        $tree = "<ul style=\"display:none\" class=\"ul_item\">\n";
        foreach ($permissions as $perm_node) {
            if($perm_node->is_root()){
                return $this->make_tree_directory($node_obj);
            }else{
                if( $node_obj->is_first() ){
                    if($perm_node->get_hash() === $node_obj->get_hash()){
                        return $this->make_tree_directory($node_obj);
                    }else{
                        
                        if($this->role_model->is_allow_node($node_obj,$perm_node)){
                            $tree .= $this->make_tree_sub_directory($perm_node);
                        }
                    }
                }else{
                    //сл уровни
                    return $this->make_tree_directory($node_obj);
                }
            }
        }
        $tree .= "</ul>";
        return $tree;
    }

    public function get_tree_directory_with_chek(){
        return $this->make_tree_directory($this->node_model->get_root(),TRUE);
        
    }

    public function get_tree_node_with_chek($hash){
        return $this->make_tree_directory($this->node_model->get_node($hash),TRUE);
    }

    /**
     * Получить тайм зону из пути
     * @param string $path
     * @return int
     */
    public function get_time_zone_from_path($path){
        $pattern ="/(.*)\/\d+-TZ([+-]\d{2})-/";
        if(preg_match_all($pattern, $path, $matches)){
            $tz = (int)$matches[2][0];
        }else{
            $date_time = new DateTime('now', new DateTimeZone('Europe/Moscow'));
            $tzmin = $date_time->getOffset();
            $tz = $tzmin / 3600;
        }
        return $tz;
    }

    ////////////////////////////////////v2.0 new func
    
    /**
     * Получить все первые узлы
     * @param array $permissions
     * @return array
     */
    private function get_all_first_nodes($permissions){
        $first_nodes_ary = array();
        foreach ($permissions as $perm_obj) {
            $first_node = $this->node_model->get_first_node($perm_obj);
            if (!array_key_exists($first_node->get_hash(), $first_nodes_ary)) {
                $first_nodes_ary[$first_node->get_hash()] = $first_node;
            }
        }
        return $first_nodes_ary;
    }
    
    /**
     * 
     * @param string $node_hash
     * @return string
     */
    private function folder_status($node_hash) {
        $status['is_open'] = array_key_exists($node_hash, $this->u_menu);
        if ($status['is_open']) {
            $status['folder_image'] = $this->config->item('folder_image_open');
            $status['folder_status'] = " loaded";
        } else {
            $status['folder_image']= $this->config->item('folder_image');
            $status['folder_status'] = '';
        }
        return $status;
    }
    
    /**
     * Alias func get_list_childs_charts_from_resolv
     * @param string $parent_node_hash
     * @param boolean $onlychild
     * @return array Nodes
     */
    public function get_list_nodes($node_hash,$onlychild){ // $node_hash == $parent_node_hash
        $node_obj = $this->node_model->get_node($node_hash);
        $permissions = $this->role_model->get_permissions($this->session->userdata['role']);
        
        if(array_key_exists(0, $permissions)){
            return $this->make_list_nodes($node_obj,$onlychild);
        }else{
            return $this->make_list_nodes_with_permissions($node_obj, $permissions, $onlychild);
        }
    }
    
    /**!!!
     * Создать плоский список узлов без учета прав доступа, подходит если админ
     * @param BynaryNode $node_obj
     * @param boolean $only_leaf
     * @return array BynaryNode
     */
    private function make_list_nodes($node_obj, $only_leaf=false){
        if($node_obj->is_folder()){
            $ary_child = $this->node_model->get_children($node_obj->get_id(),true,$only_leaf);
            
            if($only_leaf){
                return $ary_child;
            }else{
                $fold_ary = array();
                $leaf_ary = array();
                foreach ($ary_child as $child_obj) {
                    if($child_obj->is_folder()){
                        $fold_ary = array_merge($fold_ary,$this->make_list_nodes($child_obj, $only_leaf));
                    }else{
                        $leaf_ary[$child_obj->get_hash()] = $child_obj;
                    }
                }
                return array_merge($fold_ary, $leaf_ary);
//            return array_merge($leaf_ary, $fold_ary); //альтернативный порядок вывода листа,
            }
        }else{
            return array($node_obj->get_hash() => $node_obj);
        }
    }
    
    /**!!!
     * Создать плоский список узлов с учетом прав доступа
     * @param BynaryNode $node_obj
     * @param array $permissions
     * @param boolean $only_leaf
     * @return array BynaryNode
     */
    private function make_list_nodes_with_permissions($node_obj, $permissions, $only_leaf = false) {
        $ary = array();
        foreach ($permissions as $perm_node) {
            if ($node_obj->get_hash() === $perm_node->get_hash()) {
                $ary = array_merge($ary, $this->make_list_nodes($perm_node,$only_leaf));
            } else {
                
                if($node_obj->is_first()){
                    if ($this->role_model->is_allow_node($node_obj, $perm_node)) {
                        if($node_obj->is_folder()){
                            $ary = array_merge($ary, $this->make_list_nodes_with_permissions($perm_node,$permissions,$only_leaf));
                        }else{
                            $ary = array_merge($ary, array($node_obj->get_hash() => $node_obj));
                        }
                    }                    
                }else{
                    if (stripos($node_obj->get_path(),$perm_node->get_hash()) !== FALSE) {
                        if($node_obj->is_folder()){
                            $ary = array_merge($ary, $this->make_list_nodes($node_obj,$permissions,$only_leaf));
                        }else{
                            $ary = array_merge($ary, array($node_obj->get_hash() => $node_obj));
                        }
                    }                    
                }             
            }
        }
        return $ary;
    }
}